package cloud.xiangyixiang.www.spring.boot.java.basics.controller;

import cloud.xiangyixiang.www.spring.boot.java.basics.utils.Image2TextUtil;
import com.sun.org.apache.bcel.internal.generic.NEW;

import java.io.*;
import java.util.Arrays;

/**
 * <p>
 * JAVA IO 操作
 * </p>
 *
 * @author zhixinglu
 * @date 2023/9/4 10:43
 */
public class IoController {

    /**
     * 根路径
     */
    private static final String ROOT_PATH = System.getProperty("user.dir") + "/spring-boot-java-basics/src/main/resources/";

    /**
     * 测试文件路径
     */
    private static final String FILE_PATH = ROOT_PATH + "io.txt";

    /**
     * 测试中文文件路径
     */
    private static final String CHINESE_FILE_PATH = ROOT_PATH + "io-chinese.txt";

    private File file;

    private File fileChinese = null;

    public IoController() {
        this.file = new File(FILE_PATH);
        this.fileChinese = new File(CHINESE_FILE_PATH);
    }

    public static void main(String[] args) {
        description();

        test1(true);
        test1(false);

        test2();

        test3();

        test4();

        test5();

        test6();
    }


    /**
     * 介绍描述
     */
    public static void description() {
        System.out.println("介绍描述：========================");

        System.out.println("I/O流的分类: ");
        System.out.println("  根据处理数据类型的不同分为：字符流和字节流。");
        System.out.println("  根据数据流向不同分为：输入流和输出流。");


        System.out.println("优先选用字节流。首先因为硬盘上的所有文件都是以字节的形式进行传输或者保存的，包括图片等。但是字符只是在内存中才会形成的，所以在开发中，字节流使用广泛。");

        System.out.println();
    }

    /**
     * 字节流读取文件：单个字符读取
     * @param bChineseFile {@link String}
     */
    private static void test1(boolean bChineseFile) {
        System.out.println("字节流读取文件：单子字符读取：=================");
        IoController ioController = new IoController();
        FileInputStream fis = null;
        try {
            if(bChineseFile) {
                // 测试字节流读取中文乱码问题
                fis = new FileInputStream(CHINESE_FILE_PATH);
                System.out.println("test1, 中文内容结果如下：");
            } else {
                assert ioController.file != null;
                fis = new FileInputStream(ioController.file);
                System.out.println("test1, 英文内容结果如下：");
            }

            int read;
            while ( ( read = fis.read() ) != -1 ) {
                log((char)read, false);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("\n");
        }
    }

    /**
     * 字节流读取文件：数组循环读取
     */
    private static byte[] test2() {
        System.out.println("字节流读取文件：数组循环读取：======================");
        FileInputStream fis = null;
        int len = 512;
        byte[] buffer = new byte[len];
        try {
            fis = new FileInputStream(FILE_PATH);
            while ( fis.read(buffer,0, len) != -1 ) {
                log(Arrays.toString(buffer), true, true);
            }
            for(byte b : buffer) {
                // Character.isLetterOrDigit 判断字符是字母或数字，是true不是false
                if(Character.isLetterOrDigit((char) b) || (char)b == '\n') {
                    log((char)b, false, true);
                }
            }
        } catch (IOException e) {
            System.out.println("test2 发生错误，错误信息如下：" + e.getMessage());
        } finally {
            if(fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("\n");
        }
        return buffer;
    }

    /**
     * 字符流读取中文文档，解决字节流读取中文乱码问题
     */
    private static void test3() {
        System.out.println("字符流读取中文文档，解决字节流读取中文乱码问题：================");
        FileReader fr = null;
        try {
            fr = new FileReader(CHINESE_FILE_PATH);
            int read = 0;
            while ( (read = fr.read()) != -1) {
                log((char)read, false);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("\n");
        }
    }

    /**
     * 字节流写操作
     * @throws IOException
     * @throws FileNotFoundException
     */
    private static void test4() {
        System.out.println("字节流写操作：=========================");
        String outPath = ROOT_PATH + "io-new.txt";
        FileOutputStream fos = null;
        try {
            File file = new File(outPath);
            byte[] buffer = test2();
            fos = new FileOutputStream(file);
            fos.write(buffer);
        } catch (FileNotFoundException e) {
            log("FileNotFoundException: " + e);
        } catch (IOException e) {
            log("IOException: " + e);
        } finally {
            if(fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            System.out.println();
        }
    }

    /**
     * 字符流写操作
     * @throws IOException
     * @throws FileNotFoundException
     */
    private static void test5() {
        String outPath = ROOT_PATH + "io-chinese-new.txt";
        FileReader fr = null;
        FileWriter fw = null;
        try {
            fr = new FileReader(CHINESE_FILE_PATH);
            StringBuilder sb = new StringBuilder();

            int read;
            while ((read = fr.read()) != -1) {
                log((char)read, false);
                sb.append((char)read);
            }

            File file = new File(outPath);
            fw = new FileWriter(file);
            fw.write(sb.toString());
        } catch (FileNotFoundException e) {
            log("FileNotFoundException: " + e);
        } catch (IOException e) {
            log("IOException: " + e);
        } finally {
            if(fw != null) {
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 图片和byte数组互转
     */
    private static void test6(){
        System.out.println("图片和byte数组互转：===============");

        String path = ROOT_PATH + "1.png";
        byte[] image2byte = Image2TextUtil.image2byte(path);
        System.out.println("image2byte: " + Arrays.toString(image2byte));
        String path2 = ROOT_PATH + "2.png";
        Image2TextUtil.byte2image(image2byte, path2);

    }

    /**
     * 打印日志
     * @param msg {@link Object}
     */
    private static void log(Object msg) {
        log(msg, true, true);
    }

    /**
     * 打印日志
     * @param msg 带输出信息
     * @param bWrap {@link boolean} 是否换行
     */
    private static void log(Object msg, boolean bWrap) {
        if(bWrap) {
            System.out.println(msg + "");
        } else {
            System.out.print(msg + "");
        }
    }

    /**
     * 打印日志
     * @param msg 带输出信息
     * @param bWrap 是否换行
     * @param out 是否输出
     */
    private static void log(Object msg, boolean bWrap, boolean out) {
        if(out) {
            if(bWrap) {
                System.out.println(msg + "");
            }else {
                System.out.print(msg + "");
            }
        }
    }

}
